/**
 * Copyright 2010 Jake Jackson
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jake.nb.ext.ant.gotoimpl;

import java.io.File;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import org.apache.tools.ant.Location;
import org.jake.nb.ext.ant.parser.AntParser;
import org.netbeans.editor.BaseDocument;
import org.netbeans.lib.editor.hyperlink.spi.HyperlinkType;
import org.openide.cookies.LineCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.text.Line;
import org.openide.util.Exceptions;

/**
 * A class to open the file at the correct line for the selected target.
 * @author JakeJ
 */
public final class GotoDefinitionHelper {

  private GotoDefinitionHelper() {
  }

  /**
   * Opens the file the target given with passed offset is defined in.
   * @param doc the document to look for target to open in
   * @param offset the offset to look at
   * @param type the type of the hyperlink selected (deprecated)
   */
  public static void gotoDefinition(final Document doc, final int offset, final HyperlinkType type) {
    final String targetName = getTargetName(doc, offset, type);
    if (!"".equals(targetName)) { // NOI18N
      final File fileForTargetName = AntParser.getFileForTargetName(doc, targetName, offset);
      if(fileForTargetName != null) {

        final FileObject fileObject = FileUtil.toFileObject(fileForTargetName);

        try {
          final DataObject dataObject = DataObject.find(fileObject);
          final Location location = AntParser.getLocation(fileForTargetName, targetName);
          if(location != null) {
            final LineCookie lineCookie = dataObject.getLookup().lookup(LineCookie.class);
            final Line line = lineCookie.getLineSet().getOriginal(location.getLineNumber() - 1);
            line.show(Line.ShowOpenType.OPEN, Line.ShowVisibilityType.FOCUS);
          }
        } catch (DataObjectNotFoundException ex) {
          Exceptions.printStackTrace(ex);
        }
      }
    }
  }

  /**
   * Gets the name of the target under the passed offset (if any).
   * @param doc the document to lookup
   * @param offset the offset to look at in the passed document
   * @param type the type of the hypelink (deprecated)
   * @return a string with the target name pointed to at the passed offset in the passed doument or {@code null} if it
   * couldn't be found
   */
  public static String getTargetName(final Document doc, final int offset, final HyperlinkType type) {
    String retValue = null;
    final int[] span = getSpan(doc, offset, type);

    if (span != null) {
      try {
        retValue = doc.getText(span[0], span[1] - span[0]);
      } catch (BadLocationException ex) {
        Exceptions.printStackTrace(ex);
      }
    }
    return retValue == null ? "" : retValue; // NOI18N
  }

  /**
   * Gets the span of a pointing target under the offset in the passed document.
   * @param doc the document to look in
   * @param offset the offset to look at
   * @param type the hyperlink type (deprecated)
   * @return the psan where the first index is the start and the last index the end position of the  pointing target
   */
  public static int[] getSpan(final Document doc, final int offset, final HyperlinkType type) {
    return doc instanceof BaseDocument ? AntParser.getClickableTarget(doc, offset) : null;
  }

}
